﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Xml;
using Navigant.Infrastructure.Cases;
using Navigant.Infrastructure.ClientPortals;
using Navigant.Infrastructure.DomainBase;
using Navigant.Infrastructure.Helpers;
using Navigant.Model.Cases;

namespace Navigant.Model.ClientPortals
{
    public class ClientPortal : IClientPortal, IAggregateRoot
    {
        #region Constants

        public static class Constants
        {
            public const string EmailAuthenticationNotRequiredKey = "emailAuthenticationNotRequired";
            public const string AcknowledgementsShutdownKey = "acknowledgementsShutdown";
            public const string PeopleImportConnectionStringField = "PeopleImportConnectionString";
            public const string PeopleImportProfileMappingsField = "PeopleImportProfileMappings";
            public const string CustodianTerminatedFieldNameKey = "custodianTerminatedFieldName";
            public const string DefaultFromEmailAddressKey = "defaultFromEmailAddress";
            public const string ShowNonPersonCustodiansInNoticeSendingKey = "showNonPersonCustodiansInNoticeSending";
            public const string DoNotSendToTerminatedCustodiansKey = "doNotSendToTerminatedCustodians";
            public const string FixLineBreaksKey = "fixLineBreaks";
            public const string AcknowledgementsShutdownMessageKey = "acknowledgementsShutdownMessage";
            public const string CustodianReportLibrarySetting = "ReportLibrary";
        }

        #endregion

        #region Private Fields

        private List<ICase> cases;
        private Guid id;
        private string name;
        private string ownerEmail;
        private string secondaryContactEmail;
        private Uri siteAddress;
        private Dictionary<string, string> configurationSettings;
        private bool? emailAuthenticationNotRequired;
        private bool? acknowledgementsShutdown;
        private bool? fixLineBreaks;
        private bool? showNonPersonCustodiansInNoticeSending;
        private string acknowledgementsShutdownMessage;
        private string peopleImportConnectionString;
        private string peopleImportProfileMappings;
        private string custodianTerminatedFieldName;
        private string defaultFromEmailAddress;
        private bool? doNotSendToTerminatedCustodians;

        #endregion

        #region Constructors

        internal ClientPortal(IClientPortal clientPortal)
            : this(clientPortal.Id, clientPortal.Name,
            clientPortal.SiteAddress, clientPortal.OwnerEmail,
            clientPortal.SecondaryContactEmail)
        {
            foreach (string key in clientPortal.ConfigurationSettings.Keys)
            {
                this.configurationSettings.Add(key, clientPortal.ConfigurationSettings[key]);
            }
        }

        public ClientPortal(Guid id, string name, Uri siteAddress,
            string ownerEmail, string secondaryContactEmail)
        {
            this.id = id;
            this.name = name;
            this.ownerEmail = ownerEmail;
            this.secondaryContactEmail = secondaryContactEmail;
            this.SetSiteAddress(siteAddress);
            this.configurationSettings = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
        }

        #endregion

        #region Cases

        public ReadOnlyCollection<ICase> Cases
        {
            get 
            {
                // Lazy load implementation
                if (this.cases == null)
                {
                    IList<ICase> caseSites = ClientPortalService.FindAllCases(this.Id);
                    this.cases = new List<ICase>();
                    foreach (ICase caseSite in caseSites)
                    {
                        this.cases.Add(new Case(caseSite));
                    }
                }
                return this.cases.AsReadOnly(); 
            }
        }

        #endregion

        #region IEntity Members

        public object Key
        {
            get { return this.id; }
        }

        #endregion

        #region IClientPortal Members

        public Guid Id
        {
            get { return this.id; }
        }

        public string Name
        {
            get { return this.name; }
        }

        public string OwnerEmail
        {
            get { return this.ownerEmail; }
        }

        public string SecondaryContactEmail
        {
            get { return this.secondaryContactEmail; }
        }

        public Uri SiteAddress
        {
            get { return this.siteAddress; }
        }

        public IDictionary<string, string> ConfigurationSettings
        {
            get { return this.configurationSettings; }
        }

        public bool EmailAuthenticationNotRequired
        {
            get
            {
                if (!this.emailAuthenticationNotRequired.HasValue)
                {
                    this.emailAuthenticationNotRequired = ConfigurationSettingsHelper.GetBoolean(this, 
                        Constants.EmailAuthenticationNotRequiredKey);
                }
                return this.emailAuthenticationNotRequired.Value;
            }
        }

        public bool AcknowledgementsShutdown
        {
            get
            {
                if (!this.acknowledgementsShutdown.HasValue)
                {
                    this.acknowledgementsShutdown = ConfigurationSettingsHelper.GetBoolean(this, 
                        Constants.AcknowledgementsShutdownKey);
                }
                return this.acknowledgementsShutdown.Value;
            }
        }

        public bool FixLineBreaks
        {
            get
            {
                if (!this.fixLineBreaks.HasValue)
                {
                    this.fixLineBreaks = ConfigurationSettingsHelper.GetBoolean(this,
                        Constants.FixLineBreaksKey);
                }
                return this.fixLineBreaks.Value;
            }
        }

        public bool ShowNonPersonCustodiansInNoticeSending
        {
            get
            {
                if (!this.showNonPersonCustodiansInNoticeSending.HasValue)
                {
                    this.showNonPersonCustodiansInNoticeSending = ConfigurationSettingsHelper.GetBoolean(this,
                        Constants.ShowNonPersonCustodiansInNoticeSendingKey);
                }
                return this.showNonPersonCustodiansInNoticeSending.Value;
            }
        }

        public string AcknowledgementsShutdownMessage
        {
            get
            {
                if (this.acknowledgementsShutdownMessage == null)
                {
                    this.acknowledgementsShutdownMessage = ConfigurationSettingsHelper.GetString(this,
                        Constants.AcknowledgementsShutdownMessageKey);
                }
                return this.acknowledgementsShutdownMessage;
            }
        }

        public string PeopleImportConnectionString
        {
            get
            {
                if (this.peopleImportConnectionString == null)
                {
                    this.peopleImportConnectionString = ConfigurationSettingsHelper.GetString(this,
                        Constants.PeopleImportConnectionStringField);
                }
                return this.peopleImportConnectionString;
            }
        }

        public string PeopleImportProfileMappings
        {
            get
            {
                if (this.peopleImportProfileMappings == null)
                {
                    this.peopleImportProfileMappings = ConfigurationSettingsHelper.GetString(this,
                        Constants.PeopleImportProfileMappingsField);
                }
                return this.peopleImportProfileMappings;
            }
        }

        public string CustodianTerminatedFieldName 
        {
            get
            {
                if (this.custodianTerminatedFieldName == null)
                {
                    this.custodianTerminatedFieldName = ConfigurationSettingsHelper.GetString(this,
                        Constants.CustodianTerminatedFieldNameKey);
                }
                return this.custodianTerminatedFieldName;
            }
        }

        public string DefaultFromEmailAddress
        {
            get
            {
                if (this.defaultFromEmailAddress == null)
                {
                    this.defaultFromEmailAddress = ConfigurationSettingsHelper.GetString(this,
                        Constants.DefaultFromEmailAddressKey);
                }
                return this.defaultFromEmailAddress;
            }
        }

        public bool DoNotSendToTerminatedCustodians 
        {
            get
            {
                if (!this.doNotSendToTerminatedCustodians.HasValue)
                {
                    this.doNotSendToTerminatedCustodians = ConfigurationSettingsHelper.GetBoolean(this,
                        Constants.DoNotSendToTerminatedCustodiansKey);
                }
                return this.doNotSendToTerminatedCustodians.Value;
            }
        }

        public void SaveXmlFileToReportsDocumentLibrary(XmlDocument document, string fileName)
        {
            string documentLibraryName = ConfigurationSettingsHelper.GetString(this, 
                Constants.CustodianReportLibrarySetting);

            if (string.IsNullOrEmpty(documentLibraryName))
            {
                throw new ArgumentException(string.Format("The {0} client portal is missing a configuration setting for the reports library name.",
                    this.Name), Constants.CustodianReportLibrarySetting);
            }
            else
            {
                ClientPortalService.SaveXmlFileToDocumentLibrary(this, document,
                    documentLibraryName, fileName);
            }
        }

        #endregion

        #region ToString

        public override string ToString()
        {
            return this.Name;
        }

        #endregion

        #region SetSiteAddress

        private void SetSiteAddress(Uri siteAddress)
        {
            // Account for the fact the Scheme (protocol) of the 
            // Case Uri may be incorrect
            this.siteAddress = siteAddress.ToValidUri();
        }

        #endregion
    }
}
